import React, { useEffect, useRef, useState, useCallback } from 'react';
import { Spin } from 'antd';
import './ModelDependencyGraph.less';

interface Node {
    id: string;
    name?: string;
    label?: string;
    type?: string;
    description?: string;
    is_current?: boolean;
    x?: number;
    y?: number;
}

interface Edge {
    source: string;
    target: string;
    type?: string;
    label?: string;
}

interface DependencyGraphData {
    nodes: Node[];
    edges: Edge[];
    model_info?: any;
    statistics?: any;
}

interface Props {
    data: DependencyGraphData | null;
    loading?: boolean;
    width?: number;
    height?: number;
}

const ModelDependencyGraph: React.FC<Props> = ({ 
    data, 
    loading = false, 
    width = 800, 
    height = 500 
}) => {
    const svgRef = useRef<SVGSVGElement>(null);
    const [processedNodes, setProcessedNodes] = useState<Node[]>([]);
    const [hoveredNode, setHoveredNode] = useState<string | null>(null);
    const [draggedNode, setDraggedNode] = useState<string | null>(null);
    const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 });
    const [tooltip, setTooltip] = useState<{ x: number; y: number; content: any } | null>(null);

    // 改进的力导向布局算法
    const calculateForceLayout = useCallback((nodes: Node[], edges: Edge[], width: number, height: number) => {
        const centerX = width / 2;
        const centerY = height / 2;
        const padding = 60;
        
        // 初始化节点位置
        const processedNodes = nodes.map((node, index) => {
            if (node.is_current) {
                // 当前模型放在中心
                return {
                    ...node,
                    x: centerX,
                    y: centerY
                };
            } else {
                // 其他节点随机分布
                const angle = (2 * Math.PI * index) / nodes.length;
                const radius = Math.min(width, height) * 0.25;
                return {
                    ...node,
                    x: centerX + radius * Math.cos(angle) + (Math.random() - 0.5) * 100,
                    y: centerY + radius * Math.sin(angle) + (Math.random() - 0.5) * 100
                };
            }
        });

        // 简化的力导向算法
        for (let i = 0; i < 50; i++) {
            // 排斥力
            for (let j = 0; j < processedNodes.length; j++) {
                for (let k = j + 1; k < processedNodes.length; k++) {
                    const nodeA = processedNodes[j];
                    const nodeB = processedNodes[k];
                    const dx = nodeB.x! - nodeA.x!;
                    const dy = nodeB.y! - nodeA.y!;
                    const distance = Math.sqrt(dx * dx + dy * dy);
                    
                    if (distance > 0 && distance < 120) {
                        const force = 500 / (distance * distance);
                        const fx = (dx / distance) * force;
                        const fy = (dy / distance) * force;
                        
                        nodeA.x! -= fx * 0.5;
                        nodeA.y! -= fy * 0.5;
                        nodeB.x! += fx * 0.5;
                        nodeB.y! += fy * 0.5;
                    }
                }
            }

            // 连接力
            edges.forEach(edge => {
                const sourceNode = processedNodes.find(n => n.id === edge.source);
                const targetNode = processedNodes.find(n => n.id === edge.target);
                
                if (sourceNode && targetNode) {
                    const dx = targetNode.x! - sourceNode.x!;
                    const dy = targetNode.y! - sourceNode.y!;
                    const distance = Math.sqrt(dx * dx + dy * dy);
                    const idealDistance = 100;
                    
                    if (distance > 0) {
                        const force = (distance - idealDistance) * 0.05;
                        const fx = (dx / distance) * force;
                        const fy = (dy / distance) * force;
                        
                        sourceNode.x! += fx;
                        sourceNode.y! += fy;
                        targetNode.x! -= fx;
                        targetNode.y! -= fy;
                    }
                }
            });

            // 边界约束
            processedNodes.forEach(node => {
                const nodeRadius = node.is_current ? 30 : 20;
                node.x! = Math.max(padding, Math.min(width - padding, node.x!));
                node.y! = Math.max(padding, Math.min(height - padding, node.y!));
            });
        }

        return processedNodes;
    }, []);

    useEffect(() => {
        if (data?.nodes) {
            const layoutNodes = calculateForceLayout(data.nodes, data.edges || [], width, height);
            setProcessedNodes(layoutNodes);
        } else {
            setProcessedNodes([]);
        }
    }, [data, width, height, calculateForceLayout]);

    const getNodeColor = (node: Node) => {
        if (node.is_current) return '#52c41a';
        if (node.type === 'model') return '#1890ff';
        if (node.type === 'dataset') return '#722ed1';
        return '#fa8c16';
    };

    const getNodeRadius = (node: Node) => {
        return node.is_current ? 30 : 20;
    };

    const handleMouseDown = useCallback((e: React.MouseEvent, nodeId: string) => {
        e.preventDefault();
        e.stopPropagation();
        setDraggedNode(nodeId);
        
        const node = processedNodes.find(n => n.id === nodeId);
        if (node && svgRef.current) {
            const rect = svgRef.current.getBoundingClientRect();
            setDragOffset({
                x: e.clientX - rect.left - node.x!,
                y: e.clientY - rect.top - node.y!
            });
        }
    }, [processedNodes]);

    const handleMouseMove = useCallback((e: React.MouseEvent) => {
        if (draggedNode && svgRef.current) {
            const rect = svgRef.current.getBoundingClientRect();
            const newX = e.clientX - rect.left - dragOffset.x;
            const newY = e.clientY - rect.top - dragOffset.y;
            
            setProcessedNodes(prev => prev.map(node => 
                node.id === draggedNode 
                    ? { 
                        ...node, 
                        x: Math.max(30, Math.min(width - 30, newX)),
                        y: Math.max(30, Math.min(height - 30, newY))
                    }
                    : node
            ));
        }
    }, [draggedNode, dragOffset, width, height]);

    const handleMouseUp = useCallback(() => {
        setDraggedNode(null);
        setDragOffset({ x: 0, y: 0 });
    }, []);

    const handleNodeMouseEnter = useCallback((e: React.MouseEvent, node: Node) => {
        if (draggedNode) return; // 拖拽时不显示tooltip
        
        setHoveredNode(node.id);
        if (svgRef.current) {
            const rect = svgRef.current.getBoundingClientRect();
            setTooltip({
                x: e.clientX - rect.left,
                y: e.clientY - rect.top,
                content: node
            });
        }
    }, [draggedNode]);

    const handleNodeMouseLeave = useCallback(() => {
        if (!draggedNode) {
            setHoveredNode(null);
            setTooltip(null);
        }
    }, [draggedNode]);

    const renderEdges = () => {
        if (!data?.edges || processedNodes.length === 0) return null;

        return data.edges.map((edge, index) => {
            const sourceNode = processedNodes.find(n => n.id === edge.source);
            const targetNode = processedNodes.find(n => n.id === edge.target);
            
            if (!sourceNode || !targetNode) return null;

            const dx = targetNode.x! - sourceNode.x!;
            const dy = targetNode.y! - sourceNode.y!;
            const distance = Math.sqrt(dx * dx + dy * dy);
            
            if (distance === 0) return null;

            // 计算箭头起始和结束位置，避免与节点重叠
            const sourceRadius = getNodeRadius(sourceNode);
            const targetRadius = getNodeRadius(targetNode);
            
            const startX = sourceNode.x! + (dx / distance) * sourceRadius;
            const startY = sourceNode.y! + (dy / distance) * sourceRadius;
            const endX = targetNode.x! - (dx / distance) * (targetRadius + 8); // 给箭头留空间
            const endY = targetNode.y! - (dy / distance) * (targetRadius + 8);

            return (
                <g key={`edge-${edge.source}-${edge.target}-${index}`}>
                    <line
                        x1={startX}
                        y1={startY}
                        x2={endX}
                        y2={endY}
                        stroke="#666"
                        strokeWidth="2"
                        strokeDasharray={edge.type === 'dependency' ? '0' : '5,5'}
                        markerEnd="url(#arrowhead)"
                    />
                    {edge.label && distance > 60 && (
                        <text
                            x={(startX + endX) / 2}
                            y={(startY + endY) / 2}
                            textAnchor="middle"
                            fontSize="10"
                            fill="#666"
                            style={{ pointerEvents: 'none' }}
                        >
                            {edge.label}
                        </text>
                    )}
                </g>
            );
        });
    };

    const renderNodes = () => {
        return processedNodes.map(node => {
            const radius = getNodeRadius(node);
            const color = getNodeColor(node);
            const isHovered = hoveredNode === node.id;
            const isDragged = draggedNode === node.id;

            return (
                <g key={node.id}>
                    <circle
                        cx={node.x}
                        cy={node.y}
                        r={radius}
                        fill={color}
                        stroke={isHovered || isDragged ? "#000" : "rgba(255,255,255,0.8)"}
                        strokeWidth={isHovered || isDragged ? 3 : 2}
                        style={{ 
                            cursor: isDragged ? 'grabbing' : 'grab',
                            filter: isHovered ? 'brightness(1.1)' : 'none',
                            transition: isDragged ? 'none' : 'all 0.2s ease'
                        }}
                        onMouseDown={(e) => handleMouseDown(e, node.id)}
                        onMouseEnter={(e) => handleNodeMouseEnter(e, node)}
                        onMouseLeave={handleNodeMouseLeave}
                    />
                    <text
                        x={node.x}
                        y={node.y! + radius + 15}
                        textAnchor="middle"
                        fontSize="12"
                        fill="#333"
                        style={{ pointerEvents: 'none', userSelect: 'none' }}
                    >
                        {(node.label || node.name || `节点${node.id}`).substring(0, 10)}
                        {(node.label || node.name || `节点${node.id}`).length > 10 ? '...' : ''}
                    </text>
                    {node.is_current && (
                        <text
                            x={node.x}
                            y={node.y! - radius - 5}
                            textAnchor="middle"
                            fontSize="16"
                            fill="#52c41a"
                            style={{ pointerEvents: 'none', userSelect: 'none' }}
                        >
                            🎯
                        </text>
                    )}
                </g>
            );
        });
    };

    if (loading) {
        return (
            <div className="dependency-graph-loading">
                <Spin size="large" />
                <div>正在加载依赖图数据...</div>
            </div>
        );
    }

    if (!data || !data.nodes || data.nodes.length === 0) {
        return (
            <div className="dependency-graph-empty">
                <div className="empty-icon">📊</div>
                <div className="empty-title">暂无依赖关系</div>
                <div className="empty-description">该模型暂时没有发现依赖关系</div>
            </div>
        );
    }

    return (
        <div className="dependency-graph-wrapper">
            <svg
                ref={svgRef}
                width={width}
                height={height}
                className="dependency-graph-svg"
                onMouseMove={handleMouseMove}
                onMouseUp={handleMouseUp}
                onMouseLeave={handleMouseUp}
            >
                <defs>
                    <marker
                        id="arrowhead"
                        markerWidth="12"
                        markerHeight="8"
                        refX="11"
                        refY="4"
                        orient="auto"
                        markerUnits="strokeWidth"
                    >
                        <polygon points="0 0, 12 4, 0 8" fill="#666" />
                    </marker>
                </defs>
                {renderEdges()}
                {renderNodes()}
            </svg>
            
            {/* 优化的提示框 */}
            {tooltip && !draggedNode && (
                <div 
                    className="dependency-graph-tooltip"
                    style={{
                        left: tooltip.x + 20,
                        top: tooltip.y - 10,
                    }}
                >
                    <div className="tooltip-title">
                        {tooltip.content.label || tooltip.content.name || `节点${tooltip.content.id}`}
                    </div>
                    <div className="tooltip-content">
                        <div>类型: {tooltip.content.type || '未知'}</div>
                        {tooltip.content.is_current && (
                            <div style={{ color: '#52c41a' }}>🎯 当前模型</div>
                        )}
                        {tooltip.content.description && (
                            <div className="tooltip-description">
                                {tooltip.content.description}
                            </div>
                        )}
                    </div>
                </div>
            )}
            
            {/* 简化的图例 */}
            <div className="graph-legend">
                <div className="legend-item">
                    <div className="legend-color current"></div>
                    <span>当前模型</span>
                </div>
                <div className="legend-item">
                    <div className="legend-color model"></div>
                    <span>模型</span>
                </div>
                <div className="legend-item">
                    <div className="legend-color dataset"></div>
                    <span>数据集</span>
                </div>
                <div className="legend-item">
                    <div className="legend-color other"></div>
                    <span>其他</span>
                </div>
            </div>
            
            {/* 统计信息 */}
            {data.statistics && (
                <div className="graph-stats">
                    <span>节点: {data.statistics.total_nodes || processedNodes.length}</span>
                    <span>关系: {data.statistics.total_edges || (data.edges?.length || 0)}</span>
                </div>
            )}
        </div>
    );
};

export default ModelDependencyGraph;